﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SerialPort
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            init();
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

            timer1.Interval = 1000;
            timer1.Start();
        }

        private void init()
        {
            //添加事件处理程序
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
            //串口配置
            textBox_Send.Text = config.Default.sendDataText;
            comboBox_PortBps.Text = config.Default.portBps;
            comboBox_DataBit.Text = config.Default.portData;
            comboBox_StopBit.Text = config.Default.portStop;
            comboBox_Check.Text = config.Default.portCheck;

            checkBox_HexShow.Checked = config.Default.hexSendFlag;
            checkBox_TimeTick.Checked = config.Default.timeTickFlag;
            checkBox_BkColor.Checked = config.Default.rxBoxBkColor;

            checkBox_HexSend.Checked = config.Default.hexSendFlag;
            checkBox_SendNewLine.Checked = config.Default.sendNewLineFlag;
            textBox_Period.Text = config.Default.periodValue.ToString();
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string str = serialPort1.ReadExisting();//字符串方式读

            //添加时间戳
            if (checkBox_TimeTick.Checked)
            {
                    str = str.Insert(0, "[RECV " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "]");
            }

            //转换为十六进制
            if (checkBox_HexShow.Checked)
            {
                TextBox t1 = new TextBox();
                t1.Text = textBox_Recv.Text;
                tool.oxToStringTool(t1);
                t1.AppendText(str);
                tool.stringToOxTool(t1);
                textBox_Recv.Text = t1.Text;
            }
            else
            {
                textBox_Recv.AppendText(str);
            }
        }

        private void button_OpenPort_Click(object sender, EventArgs e)
        {
            if (button_OpenPort.Text.Equals("打开串口"))
            {
                try
                {
                    serialPort1.BaudRate = Convert.ToInt32(comboBox_PortBps.Text);
                    serialPort1.PortName = comboBox_PortName.Text;
                    serialPort1.StopBits = (StopBits)Convert.ToInt32(comboBox_StopBit.Text);
                    serialPort1.DataBits = Convert.ToInt32(comboBox_DataBit.Text);
                    serialPort1.Parity = (Parity)0;
                    //解决中文乱码的问题
                    serialPort1.Encoding = System.Text.Encoding.GetEncoding("GB2312");
                    serialPort1.Open();
                    button_OpenPort.Text = "关闭串口";
                }
                catch
                {
                    MessageBox.Show("串口打开失败");
                }
            }
            else
            {
                try
                {
                    serialPort1.Close();
                    button_OpenPort.Text = "打开串口";
                }
                catch
                {
                    MessageBox.Show("出现意外,串口关闭失败");
                }
            }
        }

        private void button_ClearRecv_Click(object sender, EventArgs e)
        {
            textBox_Recv.Text = "";
        }

        private void button_Send_Click(object sender, EventArgs e)
        {
            if (!button_OpenPort.Text.Equals("关闭串口"))
            {
                MessageBox.Show("请打开串口");
                return;
            }
            Thread t = new Thread(sendDataThread);
            t.Start();
        }

        private void sendDataThread()
        {
            String str = textBox_Send.Text;
            
            #region 发送十六进制
            if (checkBox_HexSend.Checked)
            {
                TextBox t = new TextBox();
                t.Text = textBox_Send.Text;
                tool.oxToStringTool(t);
                str = t.Text;
            }
            #endregion
            #region 发送字符串
            {
                String[] data = str.Split('\n');

                for (int i = 0; i < data.Length; i++)
                {
                    int pos = data[i].LastIndexOf('\r');
                    if (pos != -1)
                    {
                        sendData("[SENT " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "]"+data[i].Remove(pos));
                    }
                    else
                    {
                        sendData("[SENT " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "]"+data[i]);
                    }
                    Thread.Sleep(20);
                }
            }
            #endregion
        }

        private void button_ClearSend_Click(object sender, EventArgs e)
        {
            textBox_Send.Text = "";
        }

        private void getComPort()
        {
            string[] ports = System.IO.Ports.SerialPort.GetPortNames();//获得可用串口列表 
            string selectCom = comboBox_PortName.Text;

            //更新可用串口列表
            if (comboBox_PortName.Items.Count > 0)
            {
                comboBox_PortName.Items.Clear();
            }

            foreach (string port in ports)
            {
                comboBox_PortName.Items.Add(port);
                if (port.Equals(selectCom))
                {
                    comboBox_PortName.Text = selectCom;
                }
            }
            //如果有可用列表 则可用打开串口
            if (comboBox_PortName.Items.Count > 0)
            {
                button_OpenPort.Enabled = true;
            }
            else
            {
                comboBox_PortName.Text = "";
                button_OpenPort.Text = "打开串口";
                button_OpenPort.Enabled = false;
                if (serialPort1.IsOpen)
                {
                    serialPort1.Close();
                }
            }
        }

        private void comboBox_PortName_SelectedIndexChanged(object sender, EventArgs e)
        {
            config.Default.com = comboBox_PortName.Text;
            config.Default.Save();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            getComPort();
        }

        private void checkBox_HexSend_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_HexSend.Checked == true)
            {
                tool.stringToOxTool(textBox_Send);
            }
            else
            {
                tool.oxToStringTool(textBox_Send);
            }
        }

        private void checkBox_HexShow_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_HexShow.Checked == true)
            {
                tool.stringToOxTool(textBox_Recv);
            }
            else
            {
                tool.oxToStringTool(textBox_Recv);
            }
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            sendData(textBox_Send.Text);
        }

        private void checkBox_PeriodSend_Click(object sender, EventArgs e)
        {
            if (checkBox_PeriodSend.Checked)
            {
                try
                {
                    int time = Convert.ToInt32(textBox_Period.Text);
                    timer2.Interval = time;
                    timer2.Start();
                }
                catch
                {
                    MessageBox.Show("请输入正确的发送周期");
                    checkBox_PeriodSend.Checked = false;
                    textBox_Period.Text = "1000";
                }
            }
            else
            {
                timer2.Stop();
            }
        }

        private void textBox_Period_TextChanged(object sender, EventArgs e)
        {
            if (checkBox_PeriodSend.Checked)
            {
                timer2.Stop();
                try
                {
                    int time = Convert.ToInt32(textBox_Period.Text);
                    timer2.Interval = time;
                    timer2.Start();
                    textBox_Period.Enabled = true;
                }
                catch
                {
                    checkBox_PeriodSend.Checked = false;
                    textBox_Period.Text = "1000";
                    MessageBox.Show("请输入正确的发送周期");
                }
            }
        }

        private void judgeOx(TextBox tb, int length)
        {
            if (checkBox_HexSend.Checked == true)
            {
                char[] arr = tb.Text.ToCharArray();

                string str = tb.Text;

                if (arr.Length == 0)
                {
                    return;
                }

                char newchar = arr[arr.Length - 1];

                if (!(newchar >= 'a' && newchar <= 'f'))
                {
                    if (!(newchar >= 'A' && newchar <= 'F'))
                    {
                        if (!(newchar >= '0' && newchar <= '9'))
                        {
                            if (newchar != ' ')
                            {
                                MessageBox.Show("请输入0-9 a-z A-Z之间的值");

                                length = tb.Text.Length - length;

                                tb.Text = str.Remove(str.Length - length, length);
                                //光标停留在最后
                                tb.SelectionStart = tb.Text.Length;
                            }
                        }
                    }
                }
            }
        }

        private int lastSize = 0;

        private void textBox_Send_TextChanged(object sender, EventArgs e)
        {
            judgeOx(textBox_Send, lastSize);
            lastSize = textBox_Send.Text.Length;
        }

        private void checkBox_BkColor_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_BkColor.Checked)
            {
                textBox_Recv.BackColor = Color.White;
                textBox_Recv.ForeColor = Color.Black;
            }
            else
            {
                textBox_Recv.BackColor = Color.Black;
                textBox_Recv.ForeColor = Color.White;
            }
        }

        private void sendData(string str)
        {
            if (!button_OpenPort.Text.Equals("关闭串口"))
            {
                checkBox_PeriodSend.Checked = false;
                timer2.Stop();
                MessageBox.Show("请打开串口");
            }
            else
            {
                if (!str.Equals(""))
                {
                    if (checkBox_SendNewLine.Checked)
                    {
                        str += "\r\n"; //以0x0d 0x0a结尾
                    }
                    try
                    {
                        serialPort1.WriteLine(str);
                    }
                    catch
                    {
                        serialPort1.Close();
                    }
                }
            }
        }

        private void button_SaveRecv_Click(object sender, EventArgs e)
        {
            SaveFileDialog fileDialog = new SaveFileDialog();
            //选择文件类型
            fileDialog.Filter = "txt files(*.txt)|*.txt";
            //设置默认名
            fileDialog.FileName = "data";
            //添加扩展名
            fileDialog.AddExtension = true;
            //记录上次打开的目录
            fileDialog.RestoreDirectory = true;

            DialogResult result = fileDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                String localFilePath = fileDialog.FileName.ToString();
                //获取文件名
                //String fileName = localFilePath.Substring(localFilePath.LastIndexOf("\\")+1);
                //String filePath = localFilePath.Substring(0, localFilePath.LastIndexOf("\\"));

                FileStream file = new FileStream(localFilePath, FileMode.Create);
                //按照GB2312的格式编码
                Encoding gb = Encoding.GetEncoding("GB2312");
                byte[] data = gb.GetBytes(textBox_Recv.Text);


                file.Write(data, 0, data.Length);
                file.Flush();
                file.Close();
            }
        }

    }
}
